﻿/*+===================================================================
File:      BossOneEnemy.cpp

Summary:   Định nghĩa các phương thức của CBossOneEnemy.
===================================================================+*/

#include "BossOneEnemy.h"
#include "PlayState.h"
#include "Explosion.h"

// Các trạng thái của EnemySniper.
#define STATUS_HIDE			0
#define STATUS_RISING		1
#define STATUS_STAND_UP		2
#define STATUS_STAND		3
#define STATUS_SIT_DOWN		4
#define STATUS_HIDING		5
#define STATUS_BOT			6
#define STATUS_DIE			7

#define DIRECTION_LEFT      0
#define DIRECTION_BOT		1

#define MAX_BULLETS			3

CBossOneEnemy::CBossOneEnemy(CBill* bill, D3DXVECTOR2 pos, int id, int typeId) : CMoveableObject(pos, id, typeId)
{
	m_bill = bill;

	m_nStatus = STATUS_HIDE;
	m_pGun = new CGun(ID_ENEMY_SMALL_WHITE_BULLET, MAX_BULLETS, 1);
	m_v.y = 200.0f;

	m_box.width = 52;
	m_box.height = 80;
}


CBossOneEnemy::~CBossOneEnemy()
{
	if (m_pGun)
		delete m_pGun;
	if (m_bill)
		delete m_bill;
}

void CBossOneEnemy::UpdateAnimation()
{
	if (!m_bIsFiring)
	{
		switch (m_nStatus)
		{
			case STATUS_HIDE:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_SHELTER_HIDE);
				break;
			case STATUS_RISING:
			case STATUS_HIDING:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_SHELTER_RISE);
				break;
			case STATUS_STAND_UP:
			case STATUS_SIT_DOWN:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_SHELTER_SIT);
				break;
			case STATUS_STAND:
				if (m_nFaceDirection == DIRECTION_LEFT)
					m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_SHELTER_STAND);
				else
					m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_SHELTER_BOT);
				break;
			case STATUS_DIE:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_SHELTER_DIE);
				break;
		}
	}
	else
	{
		if (m_nStatus == STATUS_STAND)
		{
			if (m_nFaceDirection == DIRECTION_LEFT)
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_SHELTER_STAND_FIRE);
			else
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_SHELTER_BOT_FIRE);
		}
	}
}

void CBossOneEnemy::Update(float timeFrame)
{
	if (!m_bIsLive)
	{
		// Tính toán hiệu ứng khi enemy bị trúng đạn, Enemy
		// sẽ bị nảy lên đến một thời gian nào đó và nổ.
		if (m_timeDie > 0)
		{
			m_timeDie -= timeFrame;
			m_pos.y += m_v.y * timeFrame;
		}
		else if (m_timeDie < 0)
		{
			m_timeDie = 0.0f;
			Kill();
		}

		m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_SHELTER_DIE);
		return;
	}

	if (m_fTimeChange > 0)
	{
		m_fTimeChange -= timeFrame;
	}
	else
	{
		m_nStatus = (m_nStatus + 1) % 6;

		// Điều chỉnh thời gian chuyển trạng thái.
		switch (m_nStatus)
		{
		case STATUS_HIDE:
			m_fTimeChange = 1.67f;
			break;
		case STATUS_RISING:
		case STATUS_HIDING:
		case STATUS_STAND_UP:
		case STATUS_SIT_DOWN:
			m_fTimeChange = 0.1f;
			break;
		case STATUS_STAND:
			m_fTimeChange = 2.5f;
			break;
		}
	}

	// Nếu enemy đứng dậy.
	if (m_nStatus == STATUS_STAND)
	{
		if (m_fTimeChange > 1.6f)
		{
			D3DXVECTOR2 billPos = m_bill->GetPos();
			float angle = atan2(billPos.y - m_pos.y, billPos.x - m_pos.x) * 180 / PI;

			// Các góc chuyển Sprite.
			if (angle < 0 && -7.5 > angle && angle > -180 + 15)
			{
				m_nFaceDirection = DIRECTION_BOT;
			}
			else
			{
				m_nFaceDirection = DIRECTION_LEFT;
			}

			//// Công thức ảo diệu tính đc góc bắn.
			int temp = angle / 7.5;
			temp = (temp / 2) + temp % 2;
			angle = temp * 180 / 12;

			m_pGun->SetBulletAngle(angle);

			// Tính vị trí đạn bắn ra.
			D3DXVECTOR2 bulletsPos;
			if (m_nFaceDirection == DIRECTION_LEFT)
			{
				bulletsPos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f;
				bulletsPos.y = m_pos.y + m_pSprite->GetWidth() / 4.0f;
			}
			else
			{
				bulletsPos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f + 4.0f;
				bulletsPos.y = m_pos.y - 16.0f;
			}

			if (m_fTimeFire > 0)
			{
				m_fTimeFire -= timeFrame;
			}
			else
			{
				m_bIsFiring = true;
				m_pGun->Fire(bulletsPos);
				m_fTimeFire = 0.3f;
			}
		}
		else
		{
			m_bIsFiring = false;
		}
	}

	UpdateAnimation();
	m_pSprite->Update(timeFrame);
	UpdateBox(timeFrame);
}

void CBossOneEnemy::Draw()
{
	if (!m_bIsLive && m_timeDie == 0.0f)
		return;
	D3DXVECTOR2 pos = CViewport::GetInstance()->TransformMatrix(m_pos);
	if (m_pSprite)
		m_pSprite->Draw(pos);
}

void CBossOneEnemy::UpdateCollision(vector<CGameObject*> vecGameObjs, float timeFrame)
{
	if (!m_bIsLive)
		return;

	float timeCollision = timeFrame;
	CGameObject* objCollision = NULL; // Đối tượng va chạm sớm nhất.
	float normalx = 0.0f, normaly = 0.0f;

	// Xử lí va chạm với đạn của Bill
	for (int i = 0; i < CPlayState::s_billBullets.size(); i++)
	{
		if (CPlayState::s_billBullets[i]->IsLive())
		{
			float t = CheckCollision(CPlayState::s_billBullets[i], normalx, normaly, timeFrame);

			if (t < timeFrame && t < timeCollision)
			{
				// Tìm đối tượng và thời gian va chạm sớm nhất.
				timeCollision = t;
				objCollision = CPlayState::s_billBullets[i];
			}
		}
	}

	// Xử lí va chạm
	if (objCollision != NULL && m_nStatus == STATUS_STAND)
	{
		m_timeDie = 0.2f;
		m_nStatus = STATUS_DIE;
		m_bIsLive = false;

		objCollision->Kill();
	}
}

bool CBossOneEnemy::Kill()
{
	CExplosion* explosion = new CExplosion(m_pos, 0, ID_ENEMY_EXPLOSION);
	CPlayState::s_objsOutSideQuadTree.push_back(explosion);

	return true;
}

void CBossOneEnemy::Destroy()
{
	if (!m_bIsLive)
		return;

	m_timeDie = 0.1f;
	m_nStatus = STATUS_DIE;
	m_bIsLive = false;
}